#include "CoordinateY.h"

#include "CatanClassContractException.h"
#include "CatanImpossibleException.h"

namespace catan
{

/*static*/ std::vector<CoordinateY::Enum_CoordinateY> CoordinateY::vectorOfPossibleEnumValues;

/*static*/ const std::vector<CoordinateY::Enum_CoordinateY> &CoordinateY::getVectorOfPossibleEnumValues()
{
	if (vectorOfPossibleEnumValues.empty())
	{
		vectorOfPossibleEnumValues.push_back(Y0);
		vectorOfPossibleEnumValues.push_back(Y1);
		vectorOfPossibleEnumValues.push_back(Y2);
		vectorOfPossibleEnumValues.push_back(Y3);
		vectorOfPossibleEnumValues.push_back(Y4);
		vectorOfPossibleEnumValues.push_back(Y5);
		vectorOfPossibleEnumValues.push_back(Y6);
	}
	return vectorOfPossibleEnumValues;
}

/*static*/ bool CoordinateY::canInit(Enum_CoordinateY enumY)
{
	const std::vector<Enum_CoordinateY> enumValues = CoordinateY::getVectorOfPossibleEnumValues();
	for (std::vector<Enum_CoordinateY>::const_iterator enumValueIterator = enumValues.begin(); enumValueIterator != enumValues.end(); ++enumValueIterator)
	{
		if (enumY == *enumValueIterator)
		{
			return true;
		}
	}
	return false;
}

/*explicit*/ CoordinateY::CoordinateY(Enum_CoordinateY enumY): enumY(enumY)
{
	if (!CoordinateY::canInit(enumY))
	{
		throw CatanClassContractException(__FILE__, __LINE__, "CoordinateY::canInit(...) with constructor arguments should be true before creating instance.");
	}
}

CoordinateY::Enum_CoordinateY CoordinateY::getEnum() const
{
	return enumY;
}

bool CoordinateY::canCreateNeighbor(VerticalCardinal verticalCardinal) const
{
	switch (verticalCardinal.getEnum())
	{
	case VerticalCardinal::VERTICAL_TR:
	case VerticalCardinal::VERTICAL_TC:
		return CoordinateY::canInit(static_cast<Enum_CoordinateY>(enumY-1));
	case VerticalCardinal::VERTICAL_BL:
	case VerticalCardinal::VERTICAL_BC:
		return CoordinateY::canInit(static_cast<Enum_CoordinateY>(enumY+1));
	case VerticalCardinal::VERTICAL_TL:
	case VerticalCardinal::VERTICAL_BR:
		return true;
	default:
		return false;
	}
}

CoordinateY CoordinateY::createNeighbor(VerticalCardinal verticalCardinal) const
{
	if (!canCreateNeighbor(verticalCardinal))
	{
		throw CatanClassContractException(__FILE__, __LINE__, "<coordinateY>.canCreateNeighbor(...) should be true before using <coordinateY>.createNeighbor(...).");
	}
	switch (verticalCardinal.getEnum())
	{
	case VerticalCardinal::VERTICAL_TR:
	case VerticalCardinal::VERTICAL_TC:
		return CoordinateY(static_cast<Enum_CoordinateY>(enumY - 1));
	case VerticalCardinal::VERTICAL_BL:
	case VerticalCardinal::VERTICAL_BC:
		return CoordinateY(static_cast<Enum_CoordinateY>(enumY + 1));
	case VerticalCardinal::VERTICAL_TL:
	case VerticalCardinal::VERTICAL_BR:
		return *this;
	default:
		throw CatanImpossibleException(__FILE__, __LINE__, "Unexpected exception. <coordinateY>.canCreateNeighbor(...) should have thrown earlier.");
	}
}

bool CoordinateY::operator==(const CoordinateY &other) const
{
	return (enumY == other.enumY);
}

bool CoordinateY::operator<(const CoordinateY &other) const
{
	return (enumY < other.enumY);
}

CoordinateY& CoordinateY::operator=(const CoordinateY& other)
{
    if (this != &other)
    {
        enumY = other.enumY;
    }
    return *this;	
}

}
